package com.wikikii.bannerlib.banner;

import com.wikikii.bannerlib.ResourceTable;
import com.wikikii.bannerlib.banner.bean.BannerInfo;
import com.wikikii.bannerlib.banner.listener.OnBannerItemClickListener;
import com.wikikii.bannerlib.banner.listener.OnLoadImageViewListener;
import com.wikikii.bannerlib.banner.util.L;
import com.wikikii.bannerlib.banner.view.BannerBgContainer;
import com.wikikii.bannerlib.banner.view.BannerBgView;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.*;
import ohos.agp.utils.Point;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.multimodalinput.event.TouchEvent;

import java.util.ArrayList;

/**
 * 滚动视图布局 内嵌ViewPager
 */
public class LoopLayout extends DependentLayout {

    private PageSlider loopViewPager;
    private DirectionalLayout indicatorLayout;
    private DirectionalLayout animIndicatorLayout;
    private OnBannerItemClickListener onBannerItemClickListener = null;
    private OnLoadImageViewListener onLoadImageViewListener = null;
    private LoopAdapterWrapper loopAdapterWrapper;
    private int totalDistance; // Little red dot all the distance to move
    private final int size = AttrHelper.vp2px(8, getContext()); // The size of the set point;
    private ArrayList<BannerInfo> bannerInfos; // banner data
    private Image animIndicator; // Little red dot on the move
    private Image[] indicators; // Initializes the white dots
    private boolean isFirstTouch = true;
    private int index;
    private boolean isLeftMove = true;
    private Point pointerCurrentPoint = new Point();
    private Point pointerStartingPoint = new Point();

    private int normalBackground = ResourceTable.Graphic_indicator_normal_background;

    private int selectedBackground = ResourceTable.Graphic_indicator_selected_background;
    private static final int MESSAGE_LOOP = 5;
    private int loop_ms = 4000; // loop speed(ms)
    private IndicatorLocation indicatorLocation = IndicatorLocation.Center; // Indicator Location(enum values[1:left,0:depth 2:right])
    private int loop_duration = 2000; // loop rate(ms)

    private EventHandler handler = new EventHandler(EventRunner.getMainEventRunner()) {
        @Override
        public void distributeEvent(InnerEvent event) {
            super.distributeEvent(event);
            if (event.eventId == MESSAGE_LOOP) {
                if (loopViewPager.getCurrentPage() < Short.MAX_VALUE - 1) {
                    loopViewPager.setCurrentPage(loopViewPager.getCurrentPage() + 1, true);
                    sendEvent(MESSAGE_LOOP, getLoop_ms());
                }
            }
        }
    };

    boolean isScaleAnimation;

    Image enlargeView;// 放大的view
    Image narrowView;// 缩小的view

    public void setScaleAnimation(boolean scaleAnimation) {
        isScaleAnimation = scaleAnimation;
    }

    /**
     * 构造函数
     *
     * @param context 上下文
     */
    public LoopLayout(Context context) {
        super(context);
    }

    /**
     * 构造函数
     *
     * @param context 上下文
     * @param attrs   属性
     */
    public LoopLayout(Context context, AttrSet attrs) {
        super(context, attrs);
    }

    /**
     * 构造函数
     *
     * @param context      上下文
     * @param attrs        属性
     * @param defStyleAttr 样式名
     */
    public LoopLayout(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    /**
     * onBannerItemClickListener
     *
     * @param onBannerItemClickListener onBannerItemClickListener
     */
    public void setOnBannerItemClickListener(OnBannerItemClickListener onBannerItemClickListener) {
        this.onBannerItemClickListener = onBannerItemClickListener;
    }

    /**
     * OnLoadImageViewListener
     *
     * @param onLoadImageViewListener onLoadImageViewListener
     */
    public void setOnLoadImageViewListener(OnLoadImageViewListener onLoadImageViewListener) {
        this.onLoadImageViewListener = onLoadImageViewListener;
    }

    private void initializeView() {
        DisplayAttributes attributes = DisplayManager.getInstance().getDefaultDisplay(getContext()).get().getRealAttributes();
        float density = attributes.densityPixels;

        loopViewPager = new PageSlider(getContext());
        LayoutConfig loop_params = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
        addComponent(loopViewPager, loop_params);

        // FrameLayout
        StackLayout indicatorFrameLayout = new StackLayout(getContext());
        LayoutConfig f_params = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT, ((int) (20 * density)));
        f_params.addRule(LayoutConfig.HORIZONTAL_CENTER);
        f_params.addRule(LayoutConfig.ALIGN_PARENT_BOTTOM);

        switch (indicatorLocation) {
            case Left:
                f_params.addRule(LayoutConfig.ALIGN_PARENT_LEFT);
                break;
            case Right:
                f_params.addRule(LayoutConfig.ALIGN_PARENT_RIGHT);
                break;
            default:
                break;
        }

        f_params.setMargins(((int) (10 * density)), 0, ((int) (10 * density)), 0);
        addComponent(indicatorFrameLayout, f_params);

        // 指标的布局
        indicatorLayout = new DirectionalLayout(getContext());
        StackLayout.LayoutConfig ind_params = new StackLayout.LayoutConfig(StackLayout.LayoutConfig.MATCH_CONTENT, StackLayout.LayoutConfig.MATCH_PARENT);
        indicatorLayout.setOrientation(DirectionalLayout.HORIZONTAL);
        indicatorFrameLayout.addComponent(indicatorLayout, ind_params);

        // 动画指标布局
        animIndicatorLayout = new DirectionalLayout(getContext());
        StackLayout.LayoutConfig ind_params2 = new StackLayout.LayoutConfig(StackLayout.LayoutConfig.MATCH_PARENT, StackLayout.LayoutConfig.MATCH_PARENT);
        animIndicatorLayout.setOrientation(DirectionalLayout.HORIZONTAL);
        indicatorFrameLayout.addComponent(animIndicatorLayout, ind_params2);
    }

    /**
     * 确保初始化数据
     *
     * @param context context
     */
    public void initializeData(Context context) {
        initializeView();

        L.e("LoopViewPager ---> initializeData");
        if (loop_duration > loop_ms) {
            loop_duration = loop_ms;
        }

        loopViewPager.setTouchEventListener((component, touchEvent) -> {
            switch (touchEvent.getAction()) {
                case TouchEvent.PRIMARY_POINT_DOWN:
                    stopLoop(true);
                    if (isFirstTouch) {
                        pointerStartingPoint.modify(touchEvent.getPointerScreenPosition(0).getX(),
                                touchEvent.getPointerScreenPosition(0).getY());
                    }
                    break;
                case TouchEvent.POINT_MOVE:
                    stopLoop(true);
                    if (isFirstTouch) {
                        pointerCurrentPoint.modify(touchEvent.getPointerScreenPosition(0).getX(),
                                touchEvent.getPointerScreenPosition(0).getY());
                        int dx = (int) (pointerCurrentPoint.getPointX() - pointerStartingPoint.getPointX());

                        if (dx > 0) {
                            isLeftMove = false;
                        } else {
                            isLeftMove = true;
                        }
                    }
                    break;
                case TouchEvent.PRIMARY_POINT_UP:
                    isFirstTouch = false;
                    startLoop(true);
                    break;
                default:
                    break;
            }
            return true;
        });
    }

    /**
     * initialize the Data
     *
     * @param bannerInfos BannerInfo
     */
    public void setLoopData(ArrayList<BannerInfo> bannerInfos) {
        L.e("LoopViewPager ---> setLoopData");
        if (bannerInfos != null && bannerInfos.size() > 0) {
            this.bannerInfos = bannerInfos;
        } else {
            return;
        }
        if (indicatorLayout.getChildCount() > 0) {
            indicatorLayout.removeAllComponents();
            removeComponent(animIndicator);
        }
        InitIndicator();
        InitLittleRed();
        totalDistance = 2 * size * (indicators.length - 1);
        loopAdapterWrapper = new LoopAdapterWrapper(getContext(), bannerInfos, onBannerItemClickListener, onLoadImageViewListener);
        loopAdapterWrapper.setAnimation(isScaleAnimation);
        loopViewPager.setProvider(loopAdapterWrapper);
        loopViewPager.addPageChangedListener(new ViewPageChangeListener());
        index = Short.MAX_VALUE / 2 - (Short.MAX_VALUE / 2) % bannerInfos.size();
        loopViewPager.setCurrentPage(index);
    }

    private void InitIndicator() {
        indicatorLayout.removeAllComponents();
        indicators = new Image[bannerInfos.size()];
        for (int i = 0; i < indicators.length; i++) {
            indicators[i] = new Image(getContext());
            DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(size, size);
            if (i != indicators.length - 1) {
                params.setMargins(0, 0, size, 0);
            } else {
                params.setMargins(0, 0, 0, 0);
            }
            indicators[i].setLayoutConfig(params);
            indicators[i].setScaleMode(Image.ScaleMode.INSIDE);
            indicators[i].setPixelMap(ResourceTable.Media_icon_banner_indicator1);//设置默认的背景颜色
            indicatorLayout.addComponent(indicators[i]);
        }
    }

    private void InitLittleRed() {
        animIndicatorLayout.removeAllComponents();
        DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(size, size);
        animIndicator = new Image(getContext());
        animIndicator.setScaleMode(Image.ScaleMode.INSIDE);
        animIndicator.setPixelMap(ResourceTable.Media_icon_banner_indicator0);
        animIndicatorLayout.addComponent(animIndicator, params);
    }

    /**
     * 设置滚动时间
     *
     * @return 时间值
     */
    public int getLoop_ms() {
        if (loop_ms < 1500) {
            loop_ms = 1500;
        }
        return loop_ms;
    }

    /**
     * loop speed
     *
     * @param loop_ms (ms)
     */
    public void setLoop_ms(int loop_ms) {
        this.loop_ms = loop_ms;
    }

    /**
     * loop rate
     *
     * @param loop_duration (ms)
     */
    public void setLoop_duration(int loop_duration) {
        this.loop_duration = loop_duration;
    }

    /**
     * 指示器的位置
     *
     * @param indicatorLocation (enum values[1:left,0:depth,2:right])
     */
    public void setIndicatorLocation(IndicatorLocation indicatorLocation) {
        this.indicatorLocation = indicatorLocation;
    }

    /**
     * startLoop
     */
    public void startLoop() {
        handler.removeEvent(MESSAGE_LOOP);
        handler.sendEvent(MESSAGE_LOOP, getLoop_ms());
        L.e("LoopViewPager ---> startLoop");
    }

    /**
     * startLoop
     *
     * @param isFinger 是否拖拽
     */
    public void startLoop(boolean isFinger) {
        handler.removeEvent(MESSAGE_LOOP);
        handler.sendEvent(MESSAGE_LOOP, getLoop_ms());
        L.e("LoopViewPager ---> startLoop");
    }

    /**
     * stopLoop
     * 一定要在onDestroy中防止内存泄漏。
     */
    public void stopLoop() {
        handler.removeEvent(MESSAGE_LOOP);
        L.e("LoopViewPager ---> stopLoop");
    }

    /**
     * stopLoop
     *
     * @param isFinger 是否拖拽
     */
    public void stopLoop(boolean isFinger) {
        handler.removeEvent(MESSAGE_LOOP);
        L.e("LoopViewPager ---> stopLoop");

    }

    /**
     * LoopViewPager
     *
     * @return ViewPager
     */
    public PageSlider getLoopViewPager() {
        return loopViewPager;
    }

    public int getNormalBackground() {
        return normalBackground;
    }

    public void setNormalBackground(int normalBackground) {
        this.normalBackground = normalBackground;
    }

    public int getSelectedBackground() {
        return selectedBackground;
    }

    public void setSelectedBackground(int selectedBackground) {
        this.selectedBackground = selectedBackground;
    }

    BannerBgContainer bannerBgContainer;

    public void setBannerBgContainer(BannerBgContainer bannerBgContainer) {
        this.bannerBgContainer = bannerBgContainer;
    }


    float reduceValue = 0.2f;
    float upValue = 2.5f;

    /**
     * OnPageChangeListener
     */
    private class ViewPageChangeListener implements PageSlider.PageChangedListener {
        @Override
        public void onPageSliding(int position, float positionOffset, int positionOffsetPixels) {
            if (loopAdapterWrapper.getCount() > 0) {
                float length = (float) (((position % bannerInfos.size()) + (double) positionOffset) / (bannerInfos.size() - 1));
                if (length >= 1) {
                } else {
                    float path = length * totalDistance;
                    animIndicator.setTranslationX(path);
                }
                if (isScaleAnimation) {
                    Image imageView;
                    if (positionOffset == 1f) {
                        if (loopAdapterWrapper.getPrimaryItem(loopViewPager.getCurrentPage()) != null) {
                            imageView = (Image) loopAdapterWrapper.getPrimaryItem(loopViewPager.getCurrentPage()).findComponentById(ResourceTable.Id_iv_loop_banner);
                            if (imageView != null) {
                                bigIndex = loopViewPager.getCurrentPage();
                                enlargeView = imageView;
                                enLargeView();
                            }
                        }
                    } else {
                        if (bigIndex != -1) {
                            if (loopAdapterWrapper.getPrimaryItem(bigIndex) != null) {
                                imageView = (Image) loopAdapterWrapper.getPrimaryItem(bigIndex).findComponentById(ResourceTable.Id_iv_loop_banner);
                                if (!delayAnimationSet.isRunning()) {
                                    delayAnimationSet.cancel();
                                }
                                narrowView = imageView;
                                narrowView();
                            }

                        }
                    }
                }
            }

            if (bannerBgContainer == null || bannerBgContainer.getBannerBgViews().size() == 1 || bannerInfos.size() == 1) {// 判断如果是一张背景图片的话不动
                return;
            }

            BannerBgView bannerBgView;
            if (bannerBgContainer.getBannerBgViews().size() > position % bannerBgContainer.getBannerBgViews().size() + 1) {
                bannerBgView = bannerBgContainer.getBannerBgViews().get(position % bannerBgContainer.getBannerBgViews().size() + 1);
                bannerBgContainer.moveChildToFront(bannerBgView);
                bannerBgView.setImageHolder(bannerBgView.getImageView().getPixelMapHolder());
                if (index == loopViewPager.getCurrentPage() && isFirstTouch) {
                    bannerBgView.hideClipAnimation((float) (((1 - (double) positionOffset) - reduceValue) * upValue), isLeftMove ? 1 : -1);
                } else {
                    bannerBgView.hideClipAnimation((float) (((double) positionOffset - reduceValue) * upValue), positionOffsetPixels);
                }
            } else if (bannerBgContainer.getBannerBgViews().size() == position % bannerBgContainer.getBannerBgViews().size() + 1) {
                bannerBgView = bannerBgContainer.getBannerBgViews().get(0);
                bannerBgContainer.moveChildToFront(bannerBgView);
                bannerBgView.setImageHolder(bannerBgView.getImageView().getPixelMapHolder());
                bannerBgView.hideClipAnimation((float) (((double) positionOffset - reduceValue) * upValue), positionOffsetPixels);
            }
        }

        @Override
        public void onPageSlideStateChanged(int state) {
            if (state == 0) {
                if (loopAdapterWrapper.getPrimaryItem(loopViewPager.getCurrentPage()) != null) {
                    Image imageView = (Image) loopAdapterWrapper.getPrimaryItem(loopViewPager.getCurrentPage()).findComponentById(ResourceTable.Id_iv_loop_banner);
                    if (imageView != null) {
                        bigIndex = loopViewPager.getCurrentPage();
                        enlargeView = imageView;
                        enLargeView();
                    }
                }
            }
        }

        @Override
        public void onPageChosen(int position) {
            int i = position % bannerInfos.size();
            if (i == 0) {
                animIndicator.setTranslationX(totalDistance * 0.0f);
            } else if (i == bannerInfos.size() - 1) {
                animIndicator.setTranslationX(totalDistance * 1.0f);
            }
        }
    }

    AnimatorProperty scaleX;
    AnimatorProperty scaleY;

    AnimatorProperty smallScaleX;
    AnimatorProperty smallScaleY;

    AnimatorGroup delayAnimationSet = new AnimatorGroup();
    AnimatorProperty delayScaleX;
    AnimatorProperty delayScaleY;
    int bigIndex;

    float smallScaleValue = 1.0f;
    float bigScaleValue = 1.2f;

    AnimatorGroup animatorSmall;
    AnimatorGroup animatorSetsuofang;

    /**
     * 放大View
     **/
    public void enLargeView() {
        animatorSetsuofang = new AnimatorGroup();
        if (enlargeView.getScaleX() == smallScaleValue) {
            scaleX = enlargeView.createAnimatorProperty();
            scaleX.scaleXFrom(smallScaleValue).scaleX(1.35f);
            scaleY = enlargeView.createAnimatorProperty();
            scaleY.scaleYFrom(smallScaleValue).scaleY(bigScaleValue);
            animatorSetsuofang.setDuration(100);
            animatorSetsuofang.setCurveType(Animator.CurveType.LINEAR);
            animatorSetsuofang.runParallel(scaleX, scaleY);//两个动画同时开始
            animatorSetsuofang.start();
            animatorSetsuofang.setStateChangedListener(enlargeAnimatorListener);
        }
    }

    Animator.StateChangedListener enlargeAnimatorListener = new Animator.StateChangedListener() {
        @Override
        public void onStart(Animator animator) {
        }

        @Override
        public void onStop(Animator animator) {
        }

        @Override
        public void onCancel(Animator animator) {
        }

        @Override
        public void onEnd(Animator animator) {
            scaleX = null;
            scaleY = null;
            enlargeView = null;
            animatorSetsuofang.cancel();
        }

        @Override
        public void onPause(Animator animator) {
        }

        @Override
        public void onResume(Animator animator) {
        }
    };

    /**
     * 缩小View
     **/
    public void narrowView() {
        animatorSmall = new AnimatorGroup();
        if (narrowView != null && Math.abs((double) narrowView.getScaleX() - 1.35f) < .0000001) {
            smallScaleX = enlargeView.createAnimatorProperty();
            smallScaleX.scaleXFrom(1.35f).scaleX(smallScaleValue);
            smallScaleY = enlargeView.createAnimatorProperty();
            smallScaleY.scaleYFrom(bigScaleValue).scaleY(smallScaleValue);
            animatorSmall.setDuration(100);
            animatorSmall.setCurveType(Animator.CurveType.LINEAR);
            animatorSmall.runParallel(smallScaleX, smallScaleY);
            animatorSmall.start();
            bigIndex = -1;
            animatorSmall.setStateChangedListener(narrowAnimatorListener);
        }
    }

    Animator.StateChangedListener narrowAnimatorListener = new Animator.StateChangedListener() {
        @Override
        public void onStart(Animator animator) {
        }

        @Override
        public void onStop(Animator animator) {
        }

        @Override
        public void onCancel(Animator animator) {
        }

        @Override
        public void onEnd(Animator animator) {
            setNoUseObjectNull();
        }

        @Override
        public void onPause(Animator animator) {
        }

        @Override
        public void onResume(Animator animator) {
        }
    };

    /**
     * 缩小View
     *
     * @param view      Component
     * @param delayTime 延迟时间
     */
    public void narrowView(final Component view, long delayTime) {
        if (view != null) {
            delayScaleX = enlargeView.createAnimatorProperty();
            delayScaleX.scaleXFrom(bigScaleValue).scaleX(smallScaleValue);
            delayScaleY = enlargeView.createAnimatorProperty();
            delayScaleY.scaleYFrom(bigScaleValue).scaleY(smallScaleValue);
            delayAnimationSet.setDuration(200);
            delayAnimationSet.setCurveType(Animator.CurveType.LINEAR);
            delayAnimationSet.runParallel(delayScaleX, delayScaleY);//两个动画同时开始
            delayAnimationSet.setDelay(delayTime);
            delayAnimationSet.start();
        }
    }

    /**
     * 设置不用的对象为空 等待垃圾回收
     */
    private void setNoUseObjectNull() {
        smallScaleX = null;
        smallScaleY = null;
        narrowView = null;
        if (animatorSmall != null) {
            animatorSmall = null;
        }
        if (animatorSetsuofang != null) {
            animatorSetsuofang.cancel();
            animatorSetsuofang = null;
        }
    }
}
